home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / g_main.c1 < prev    next >
Encoding:
Text File  |  2002-08-14  |  9.1 KB  |  443 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20.  
  21. #include "g_local.h"
  22.  
  23. game_locals_t    game;
  24. level_locals_t    level;
  25. game_import_t    gi;
  26. game_export_t    globals;
  27. spawn_temp_t    st;
  28.  
  29. int    sm_meat_index;
  30. int    snd_fry;
  31. int meansOfDeath;
  32.  
  33. edict_t        *g_edicts;
  34.  
  35. cvar_t    *deathmatch;
  36. cvar_t    *coop;
  37. cvar_t    *dmflags;
  38. cvar_t    *skill;
  39. cvar_t    *fraglimit;
  40. cvar_t    *timelimit;
  41. cvar_t    *password;
  42. cvar_t    *spectator_password;
  43. cvar_t    *needpass;
  44. cvar_t    *maxclients;
  45. cvar_t    *maxspectators;
  46. cvar_t    *maxentities;
  47. cvar_t    *g_select_empty;
  48. cvar_t    *dedicated;
  49.  
  50. cvar_t    *filterban;
  51.  
  52. cvar_t    *sv_maxvelocity;
  53. cvar_t    *sv_gravity;
  54.  
  55. cvar_t    *sv_rollspeed;
  56. cvar_t    *sv_rollangle;
  57. cvar_t    *gun_x;
  58. cvar_t    *gun_y;
  59. cvar_t    *gun_z;
  60.  
  61. cvar_t    *run_pitch;
  62. cvar_t    *run_roll;
  63. cvar_t    *bob_up;
  64. cvar_t    *bob_pitch;
  65. cvar_t    *bob_roll;
  66.  
  67. cvar_t    *sv_cheats;
  68.  
  69. cvar_t    *flood_msgs;
  70. cvar_t    *flood_persecond;
  71. cvar_t    *flood_waitdelay;
  72.  
  73. cvar_t    *sv_maplist;
  74.  
  75. void SpawnEntities (char *mapname, char *entities, char *spawnpoint);
  76. void ClientThink (edict_t *ent, usercmd_t *cmd);
  77. qboolean ClientConnect (edict_t *ent, char *userinfo);
  78. void ClientUserinfoChanged (edict_t *ent, char *userinfo);
  79. void ClientDisconnect (edict_t *ent);
  80. void ClientBegin (edict_t *ent);
  81. void ClientCommand (edict_t *ent);
  82. void RunEntity (edict_t *ent);
  83. void WriteGame (char *filename, qboolean autosave);
  84. void ReadGame (char *filename);
  85. void WriteLevel (char *filename);
  86. void ReadLevel (char *filename);
  87. void InitGame (void);
  88. void G_RunFrame (void);
  89.  
  90.  
  91. //===================================================================
  92.  
  93.  
  94. void ShutdownGame (void)
  95. {
  96.     gi.dprintf ("==== ShutdownGame ====\n");
  97.  
  98.     gi.FreeTags (TAG_LEVEL);
  99.     gi.FreeTags (TAG_GAME);
  100. }
  101.  
  102.  
  103. /*
  104. =================
  105. GetGameAPI
  106.  
  107. Returns a pointer to the structure with all entry points
  108. and global variables
  109. =================
  110. */
  111. game_export_t *GetGameAPI (game_import_t *import)
  112. {
  113.     gi = *import;
  114.  
  115.     globals.apiversion = GAME_API_VERSION;
  116.     globals.Init = InitGame;
  117.     globals.Shutdown = ShutdownGame;
  118.     globals.SpawnEntities = SpawnEntities;
  119.  
  120.     globals.WriteGame = WriteGame;
  121.     globals.ReadGame = ReadGame;
  122.     globals.WriteLevel = WriteLevel;
  123.     globals.ReadLevel = ReadLevel;
  124.  
  125.     globals.ClientThink = ClientThink;
  126.     globals.ClientConnect = ClientConnect;
  127.     globals.ClientUserinfoChanged = ClientUserinfoChanged;
  128.     globals.ClientDisconnect = ClientDisconnect;
  129.     globals.ClientBegin = ClientBegin;
  130.     globals.ClientCommand = ClientCommand;
  131.  
  132.     globals.RunFrame = G_RunFrame;
  133.  
  134.     globals.ServerCommand = ServerCommand;
  135.  
  136.     globals.edict_size = sizeof(edict_t);
  137.  
  138.     return &globals;
  139. }
  140.  
  141. #ifndef GAME_HARD_LINKED
  142. // this is only here so the functions in q_shared.c and q_shwin.c can link
  143. void Sys_Error (char *error, ...)
  144. {
  145.     va_list        argptr;
  146.     char        text[1024];
  147.  
  148.     va_start (argptr, error);
  149.     vsprintf (text, error, argptr);
  150.     va_end (argptr);
  151.  
  152.     gi.error (ERR_FATAL, "%s", text);
  153. }
  154.  
  155. void Com_Printf (char *msg, ...)
  156. {
  157.     va_list        argptr;
  158.     char        text[1024];
  159.  
  160.     va_start (argptr, msg);
  161.     vsprintf (text, msg, argptr);
  162.     va_end (argptr);
  163.  
  164.     gi.dprintf ("%s", text);
  165. }
  166.  
  167. #endif
  168.  
  169. //======================================================================
  170.  
  171.  
  172. /*
  173. =================
  174. ClientEndServerFrames
  175. =================
  176. */
  177. void ClientEndServerFrames (void)
  178. {
  179.     int        i;
  180.     edict_t    *ent;
  181.  
  182.     // calc the player views now that all pushing
  183.     // and damage has been added
  184.     for (i=0 ; i<maxclients->value ; i++)
  185.     {
  186.         ent = g_edicts + 1 + i;
  187.         if (!ent->inuse || !ent->client)
  188.             continue;
  189.         ClientEndServerFrame (ent);
  190.     }
  191.  
  192. }
  193.  
  194. /*
  195. =================
  196. CreateTargetChangeLevel
  197.  
  198. Returns the created target changelevel
  199. =================
  200. */
  201. edict_t *CreateTargetChangeLevel(char *map)
  202. {
  203.     edict_t *ent;
  204.  
  205.     ent = G_Spawn ();
  206.     ent->classname = "target_changelevel";
  207.     Com_sprintf(level.nextmap, sizeof(level.nextmap), "%s", map);
  208.     ent->map = level.nextmap;
  209.     return ent;
  210. }
  211.  
  212. /*
  213. =================
  214. EndDMLevel
  215.  
  216. The timelimit or fraglimit has been exceeded
  217. =================
  218. */
  219. void EndDMLevel (void)
  220. {
  221.     edict_t        *ent;
  222.     char *s, *t, *f;
  223.     static const char *seps = " ,\n\r";
  224.  
  225.     // stay on same level flag
  226.     if ((int)dmflags->value & DF_SAME_LEVEL)
  227.     {
  228.         BeginIntermission (CreateTargetChangeLevel (level.mapname) );
  229.         return;
  230.     }
  231.  
  232.     // see if it's in the map list
  233.     if (*sv_maplist->string) {
  234.         s = strdup(sv_maplist->string);
  235.         f = NULL;
  236.         t = strtok(s, seps);
  237.         while (t != NULL) {
  238.             if (Q_stricmp(t, level.mapname) == 0) {
  239.                 // it's in the list, go to the next one
  240.                 t = strtok(NULL, seps);
  241.                 if (t == NULL) { // end of list, go to first one
  242.                     if (f == NULL) // there isn't a first one, same level
  243.                         BeginIntermission (CreateTargetChangeLevel (level.mapname) );
  244.                     else
  245.                         BeginIntermission (CreateTargetChangeLevel (f) );
  246.                 } else
  247.                     BeginIntermission (CreateTargetChangeLevel (t) );
  248.                 free(s);
  249.                 return;
  250.             }
  251.             if (!f)
  252.                 f = t;
  253.             t = strtok(NULL, seps);
  254.         }
  255.         free(s);
  256.     }
  257.  
  258.     if (level.nextmap[0]) // go to a specific map
  259.         BeginIntermission (CreateTargetChangeLevel (level.nextmap) );
  260.     else {    // search for a changelevel
  261.         ent = G_Find (NULL, FOFS(classname), "target_changelevel");
  262.         if (!ent)
  263.         {    // the map designer didn't include a changelevel,
  264.             // so create a fake ent that goes back to the same level
  265.             BeginIntermission (CreateTargetChangeLevel (level.mapname) );
  266.             return;
  267.         }
  268.         BeginIntermission (ent);
  269.     }
  270. }
  271.  
  272.  
  273. /*
  274. =================
  275. CheckNeedPass
  276. =================
  277. */
  278. void CheckNeedPass (void)
  279. {
  280.     int need;
  281.  
  282.     // if password or spectator_password has changed, update needpass
  283.     // as needed
  284.     if (password->modified || spectator_password->modified) 
  285.     {
  286.         password->modified = spectator_password->modified = false;
  287.  
  288.         need = 0;
  289.  
  290.         if (*password->string && Q_stricmp(password->string, "none"))
  291.             need |= 1;
  292.         if (*spectator_password->string && Q_stricmp(spectator_password->string, "none"))
  293.             need |= 2;
  294.  
  295.         gi.cvar_set("needpass", va("%d", need));
  296.     }
  297. }
  298.  
  299. /*
  300. =================
  301. CheckDMRules
  302. =================
  303. */
  304. void CheckDMRules (void)
  305. {
  306.     int            i;
  307.     gclient_t    *cl;
  308.  
  309.     if (level.intermissiontime)
  310.         return;
  311.  
  312.     if (!deathmatch->value)
  313.         return;
  314.  
  315.     if (timelimit->value)
  316.     {
  317.         if (level.time >= timelimit->value*60)
  318.         {
  319.             gi.bprintf (PRINT_HIGH, "Timelimit hit.\n");
  320.             EndDMLevel ();
  321.             return;
  322.         }
  323.     }
  324.  
  325.     if (fraglimit->value)
  326.     {
  327.         for (i=0 ; i<maxclients->value ; i++)
  328.         {
  329.             cl = game.clients + i;
  330.             if (!g_edicts[i+1].inuse)
  331.                 continue;
  332.  
  333.             if (cl->resp.score >= fraglimit->value)
  334.             {
  335.                 gi.bprintf (PRINT_HIGH, "Fraglimit hit.\n");
  336.                 EndDMLevel ();
  337.                 return;
  338.             }
  339.         }
  340.     }
  341. }
  342.  
  343.  
  344. /*
  345. =============
  346. ExitLevel
  347. =============
  348. */
  349. void ExitLevel (void)
  350. {
  351.     int        i;
  352.     edict_t    *ent;
  353.     char    command [256];
  354.  
  355.     Com_sprintf (command, sizeof(command), "gamemap \"%s\"\n", level.changemap);
  356.     gi.AddCommandString (command);
  357.     level.changemap = NULL;
  358.     level.exitintermission = 0;
  359.     level.intermissiontime = 0;
  360.     ClientEndServerFrames ();
  361.  
  362.     // clear some things before going to next level
  363.     for (i=0 ; i<maxclients->value ; i++)
  364.     {
  365.         ent = g_edicts + 1 + i;
  366.         if (!ent->inuse)
  367.             continue;
  368.         if (ent->health > ent->client->pers.max_health)
  369.             ent->health = ent->client->pers.max_health;
  370.     }
  371.  
  372. }
  373.  
  374. /*
  375. ================
  376. G_RunFrame
  377.  
  378. Advances the world by 0.1 seconds
  379. ================
  380. */
  381. void G_RunFrame (void)
  382. {
  383.     int        i;
  384.     edict_t    *ent;
  385.  
  386.     level.framenum++;
  387.     level.time = level.framenum*FRAMETIME;
  388.  
  389.     // choose a client for monsters to target this frame
  390.     AI_SetSightClient ();
  391.  
  392.     // exit intermissions
  393.  
  394.     if (level.exitintermission)
  395.     {
  396.         ExitLevel ();
  397.         return;
  398.     }
  399.  
  400.     //
  401.     // treat each object in turn
  402.     // even the world gets a chance to think
  403.     //
  404.     ent = &g_edicts[0];
  405.     for (i=0 ; i<globals.num_edicts ; i++, ent++)
  406.     {
  407.         if (!ent->inuse)
  408.             continue;
  409.  
  410.         level.current_entity = ent;
  411.  
  412.         VectorCopy (ent->s.origin, ent->s.old_origin);
  413.  
  414.         // if the ground entity moved, make sure we are still on it
  415.         if ((ent->groundentity) && (ent->groundentity->linkcount != ent->groundentity_linkcount))
  416.         {
  417.             ent->groundentity = NULL;
  418.             if ( !(ent->flags & (FL_SWIM|FL_FLY)) && (ent->svflags & SVF_MONSTER) )
  419.             {
  420.                 M_CheckGround (ent);
  421.             }
  422.         }
  423.  
  424.         if (i > 0 && i <= maxclients->value)
  425.         {
  426.             ClientBeginServerFrame (ent);
  427.             continue;
  428.         }
  429.  
  430.         G_RunEntity (ent);
  431.     }
  432.  
  433.     // see if it is time to end a deathmatch
  434.     CheckDMRules ();
  435.  
  436.     // see if needpass needs updated
  437.     CheckNeedPass ();
  438.  
  439.     // build the playerstate_t structures for all players
  440.     ClientEndServerFrames ();
  441. }
  442.  
  443.